package bebetes;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import simu.Actionnable;
import visu.Champ;
import visu.Dessinable;
import visu.PerceptionAble;
import visu.Visualisateur;

/**
 * Classe abstraite bébête.
 * 
 * Une bébête est définie par un champs de vue en degrès, une direction, une
 * vitesse de déplacement en pixels par seconde, une longueur de vue en pixels
 * et une couleur la représentant.
 * 
 * @author COLLET Philippe
 * @author gnpt
 */
public abstract class Bebete extends PerceptionAble implements Dessinable,
		Actionnable {
	// Le champ sur lequel se déplace la bébête
	protected ChampDeBebetes champ;
	// Le champs de vue associé à une bébête
	private static float champDeVue = (float) (Math.PI / 4);
	// Couleur de remplissage de la bébête
	protected Color couleur;
	// Direction courante de la bébête en radians [0 - 2 PI[
	protected float directionCourante;
	// Nb de pixel pour la longueur du champ de vue
	private static int longueurDeVue = 20;
	/*
	 * Vitesse en pixels par seconde (de type float pour conserver la précision
	 * du calcul de vitesse).
	 */
	protected float vitesseCourante;
	// Positions sur le champ 2D
	protected int x, y;

	/**
	 * Est appelée à chaque tick d'horloge du simulateur pour agiter la bébête.
	 * 
	 * @see simu.Actionnable#agit()
	 */
	@Override
	public void agit() {
		this.calculeDeplacementAFaire();
		this.effectueDeplacement();
	}

	/**
	 * Modifie les paramètres de <code>vitesse</code> et
	 * <code>directionCourante</code>.
	 */
	public abstract void calculeDeplacementAFaire();

	/**
	 * Modifie la position en fonction de <code>vitesse</code> et
	 * <code>directionCourante</code>.
	 */
	public abstract void effectueDeplacement();

	/**
	 * @see visu.Positionnable#getChamp()
	 */
	@Override
	public Champ getChamp() {
		return (Champ) this.champ;
	}

	/**
	 * @see visu.PerceptionAble#getChampDeVue()
	 */
	@Override
	public float getChampDeVue() {
		return Bebete.champDeVue;
	}

	/**
	 * @see visu.Dessinable#getCouleur()
	 */
	@Override
	public Color getCouleur() {
		return this.couleur;
	}

	/**
	 * @see visu.Dirigeable#getDirectionCourante()
	 */
	@Override
	public float getDirectionCourante() {
		return this.directionCourante;
	}

	/**
	 * @see visu.PerceptionAble#getLongueurDeVue()
	 */
	@Override
	public int getLongueurDeVue() {
		return Bebete.longueurDeVue;
	}

	/**
	 * @see visu.Dirigeable#getVitesseCourante()
	 */
	@Override
	public float getVitesseCourante() {
		return this.vitesseCourante;
	}

	/**
	 * @see visu.Positionnable#getX()
	 */
	@Override
	public int getX() {
		return this.x;
	}

	/**
	 * @see visu.Positionnable#getY()
	 */
	@Override
	public int getY() {
		return this.y;
	}

	/**
	 * Permet à la bébête de dessiner sur un contexte graphique sans effet de
	 * pixellisation.
	 * 
	 * @param g
	 *            le contexte graphique sur lequel est dessinée la bébête. Le
	 *            contexte graphique est en réalité le champs de bébête qui est
	 *            représenté à l'écran par la classe {@link Visualisateur}.
	 * 
	 * @see visu.Dessinable#seDessine(java.awt.Graphics)
	 */
	@Override
	public void seDessine(Graphics g) {
		int CDVDegres = (int) Math.toDegrees(Bebete.champDeVue);

		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		g2.setColor(this.couleur);
		g2.fillArc(this.x, this.y, Dessinable.TAILLEGRAPHIQUE,
				Dessinable.TAILLEGRAPHIQUE, -(int) Math
						.toDegrees(this.directionCourante)
						- (CDVDegres / 2), CDVDegres);
	}

	/**
	 * Mutateur pour le champ de vue de la bébête.
	 * 
	 * @param cDV
	 *            le nouveau champ de vue.
	 */
	public static void setChampDeVue(int cDV) {
		Bebete.champDeVue = cDV;
	}

	/**
	 * Mutateur pour la couleur de la bébête.
	 * 
	 * @param couleur
	 *            la nouvelle couleur de la bébête.
	 */
	@Override
	public void setCouleur(Color couleur) {
		this.couleur = couleur;
	}

	/**
	 * @see visu.Dirigeable#setDirectionCourante(float)
	 */
	@Override
	public void setDirectionCourante(float directionCourante) {
		this.directionCourante = directionCourante;
	}

	/**
	 * Mutateur pour la longueur de vue de la bébête.
	 * 
	 * @param lDV
	 *            la nouvelle longueur de vue.
	 */
	public static void setLongueurDeVue(int lDV) {
		Bebete.longueurDeVue = lDV;
	}

	/**
	 * @see visu.Dirigeable#setVitesseCourante(float)
	 */
	@Override
	public void setVitesseCourante(float vitesseCourante) {
		this.vitesseCourante = vitesseCourante;
	}

	/**
	 * @see visu.Positionnable#setX(int)
	 */
	@Override
	public void setX(int x) {
		this.x = x;
	}

	/**
	 * @see visu.Positionnable#setY(int)
	 */
	@Override
	public void setY(int y) {
		this.y = y;
	}
}
